﻿using System;
using System.Threading;
using Didaku.QEngine.Common.Entities;
using Didaku.QEngine.Common.Interfaces;
using NLog;

namespace Didaku.QEngine
{
    /// <summary>持久化服务
    /// </summary>
    internal class Persistence : IQEnginePersistence<Transaction>
    {
        private static readonly Logger _Logger = LogManager.GetCurrentClassLogger();

        public Persistence()
        {
            IsAync = false;
            string dbDate = DateTime.Now.ToString("yyyyMMdd");
            //DatabaseFile.FileName = string.Format(QFiles.DataFile.SqLiteDbFile, dbDate);
        }

        #region ILocalPersistence Members

        /// <summary>是否异步持久化
        /// </summary>
        public bool IsAync { get; set; }

        public int Add(params Transaction[] trans)
        {
            if (IsAync)
                return CallMethod(TransactionProcessMethod.Add, trans);
            return 1;
            //return TransactionController.ME.Add(trans);
        }

        public int Update(params Transaction[] trans)
        {
            if (IsAync)
                return CallMethod(TransactionProcessMethod.Update, trans);
            return 1;
            //return TransactionController.ME.Update(trans);
        }

        public int Remove(params Transaction[] trans)
        {
            if (IsAync)
                return CallMethod(TransactionProcessMethod.Remove, trans);
            return 1;
            //return TransactionController.ME.Remove(trans);
        }

        /// <summary>搜索指定队列当天的交易
        /// </summary>
        /// <param name="queueId">The queue id.</param>
        /// <returns></returns>
        public Transaction[] Select(string queueId)
        {
            return new Transaction[0];
            //return TransactionController.ME.SelectByQueue(queueId);
        }

        /// <summary>备份指定队列的号票生成计数
        /// </summary>
        public void Backup(string serviceQueueId, int currCount)
        {
            //QueueInfoController.ME.Update(serviceQueueId, currCount);
        }

        #endregion

        #region Transaction Aync Method

        private int CallMethod(TransactionProcessMethod method, params Transaction[] trans)
        {
            DataWrapper wrapper = DataWrapper.Build(method, trans);
            var back = new WaitCallback(CallBackMethod);
            if (!ThreadPool.QueueUserWorkItem(back, wrapper))
                wrapper.ThreadDispoes();
            return trans.Length;
        }

        /// <summary>一个供异步调用的WaitCallback方法
        /// </summary>
        /// <param name="datas">The send object wrapper.</param>
        protected void CallBackMethod(object datas)
        {
            if (null == datas)
                return;
            var w = (DataWrapper) datas;
            w.Thread = Thread.CurrentThread;
            try
            {
                switch (w.Method)
                {
                    case TransactionProcessMethod.Add:
                        //TransactionController.ME.Add(w.Transactions);
                        break;
                    case TransactionProcessMethod.Update:
                        //TransactionController.ME.Update(w.Transactions);
                        break;
                    case TransactionProcessMethod.Remove:
                        //TransactionController.ME.Remove(w.Transactions);
                        break;
                }
            }
            catch (Exception e)
            {
                _Logger.WarnException(string.Format("数据库操作异常。{0},{1}", w.Method, w.Transactions[0].TicketNumber), e);
            }
            finally
            {
                w.ThreadDispoes();
            }
        }

        #region Nested type: DataWrapper

        private sealed class DataWrapper
        {
            public volatile TransactionProcessMethod Method;
            public volatile Thread Thread;
            public volatile Transaction[] Transactions;

            public void ThreadDispoes()
            {
                if (null != Thread)
                    Thread.Abort();
            }

            public static DataWrapper Build(TransactionProcessMethod method, params Transaction[] transactions)
            {
                var w = new DataWrapper {Method = method, Transactions = transactions};
                return w;
            }
        }

        #endregion

        #region Nested type: TransactionProcessMethod

        private enum TransactionProcessMethod
        {
            Add,
            Update,
            Remove
        }

        #endregion

        #endregion
    }
}